﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Thrift.Utility
{
    public abstract class ThriftService
    {
        private static Hashtable interfaceCallRecord = System.Collections.Hashtable.Synchronized(new Hashtable());

        protected virtual string Excute<Q>(StandRequest<Q> request, Func<StandRequest<Q>, string> func)
        {
            Statistic(request);
            if (request.IsValid())
            {
                try
                {
                    string result = string.Empty;
                    if (func != null)
                    {
                        result = func(request);
                    }
                    StandResponse<string> response = new StandResponse<string>
                    {
                        Code = "0",
                        Desc = "SUCCESS",
                        Data = result
                    };
                    return SerializeHelper.JsonSerialize3(response);
                }
                catch (Exception ex)
                {
                    CatchException(ex);
                    StandResponse<string> response = new StandResponse<string>
                    {
                        Code = "-2",
                        Desc = "服务端异常",
                        Data = string.Empty
                    };
                    return SerializeHelper.JsonSerialize3(response);
                }
            }
            StandResponse<string> res = new StandResponse<string>
            {
                Code = "-1",
                Desc = "请求数据异常",
                Data = string.Empty
            };
            return SerializeHelper.JsonSerialize3(res);
        }

        /// <summary>
        /// 统计，每个接口的访问次数、客户端到服务端的传输时间等
        /// </summary>
        /// <typeparam name="Q"></typeparam>
        /// <param name="request"></param>
        protected virtual void Statistic<Q>(StandRequest<Q> request)
        {
            var currentRecordKey = request.MethodName + string.Format("{0:g}", DateTime.Now);
            //当前调用记录记到Hash表
            if (interfaceCallRecord.ContainsKey(currentRecordKey))
            {
                var record = (InterfaceCallRecord)interfaceCallRecord[currentRecordKey];
                record.CallTimes += 1;
                double currentNetworkDelay = (DateTime.UtcNow - request.RequestTime).TotalSeconds;
                record.TotalNetworkDelay += currentNetworkDelay;
                if(currentNetworkDelay>record.MaxNetworkDelay)
                {
                    record.MaxNetworkDelay = currentNetworkDelay;
                }
                interfaceCallRecord[currentRecordKey] = record;
            }
            else
            {
                var record = new InterfaceCallRecord();
                record.RecordHour = string.Format("{0:g}", DateTime.Now);
                record.CallTimes += 1;
                double currentNetworkDelay = (DateTime.UtcNow - request.RequestTime).TotalSeconds;
                record.TotalNetworkDelay += currentNetworkDelay;
                record.MaxNetworkDelay = currentNetworkDelay;
                interfaceCallRecord.Add(currentRecordKey, record);

                var lastRecordKey = request.MethodName + string.Format("{0:g}", DateTime.Now.AddHours(-1));
                //上一次调用记录写数据库
                if (interfaceCallRecord.ContainsKey(lastRecordKey))
                {
                    var lastRecord = (InterfaceCallRecord)interfaceCallRecord[lastRecordKey];
                    RecordStatistic(lastRecord);
                    interfaceCallRecord.Remove(lastRecordKey);
                }
            }
        }

        public virtual void RecordStatistic(InterfaceCallRecord record)
        {

        }

        /// <summary>
        /// 异常处理
        /// </summary>
        /// <param name="ex"></param>
        protected abstract void CatchException(Exception ex);
    }

    /// <summary>
    /// 每小时生成一次记录
    /// </summary>
    public class InterfaceCallRecord
    {
        /// <summary>
        /// 这条记录的时间，单位小时
        /// </summary>
        public string RecordHour { get; set; }

        /// <summary>
        /// 调用次数
        /// </summary>
        public int CallTimes { get; set; }

        /// <summary>
        /// 总网络时延，单位秒
        /// </summary>
        public double TotalNetworkDelay { get; set; }

        /// <summary>
        /// 平均网络时延
        /// </summary>
        public double AverageNetworkDelay
        {
            get
            {
                if (CallTimes != 0)
                {
                    return TotalNetworkDelay / CallTimes;
                }else
                {
                    return 0;
                }
            }
        }

        /// <summary>
        /// 最大网络时延
        /// </summary>
        public double MaxNetworkDelay { get; set; }
    }
}
